﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace Ellanet
{
    public partial class GuestImport : Form // KryptonForm
    {
        private string _guiXmlPath = null;
        private string _vmrunPath = null;
        private string _hostName = null;
        private string _credentials = null;
        private BackgroundWorker listGuestThread;
        private ArrayList guests;
        private bool listVMReturn = false;
        private ErrorProvider ep = new ErrorProvider();

        delegate void AddItemToListViewDelegate(ref ListView lv, string text, string tag);
        delegate void SetProgressBarStyleDelegate(ref ProgressBar pb, ProgressBarStyle style);

        public GuestImport(string hostName, string credentials, string guiXmlPath, string vmrunPath)
        {
            InitializeComponent();
            _hostName = hostName;
            _credentials = credentials;
            _guiXmlPath = guiXmlPath;
            _vmrunPath = vmrunPath;
            this.Load += new EventHandler(GuestImport_Load);
            guestListView.ItemSelectionChanged += new ListViewItemSelectionChangedEventHandler(guestListView_ItemSelectionChanged);
            guestListView.ItemChecked += new ItemCheckedEventHandler(guestListView_ItemChecked);
            newCredentialsButton.Click += new EventHandler(newCredentialsButton_Click);
            addButton.Click += new EventHandler(addButton_Click);
        }

        void addButton_Click(object sender, EventArgs e)
        {
            if (ValidateForm())
            {
                vmrunGUIXmlWrapper guiXmlWrapper = new vmrunGUIXmlWrapper(_guiXmlPath);

                foreach (ListViewItem lvi in guestListView.CheckedItems)
                {
                    if (!guiXmlWrapper.GuestExists(lvi.Tag.ToString(), _hostName))
                    {
                        guiXmlWrapper.AddGuest(lvi.Text, _hostName, lvi.Tag.ToString(), descriptionTextBox.Text, credentialsComboBox.Text);
                    }
                }

                guiXmlWrapper.SaveXml();
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        bool ValidateForm()
        {
            ep.Dispose();

            if (credentialsComboBox.SelectedIndex == -1)
            {
                ep.SetError(credentialsComboBox, "Please specify the Guest Credentials that should be used when managing the Guest operating system.");
                credentialsComboBox.Select();
                return false;
            }

            return true;
        }

        void newCredentialsButton_Click(object sender, EventArgs e)
        {
            Credentials cred = new Credentials(null, _guiXmlPath);

            if (cred.ShowDialog() == DialogResult.OK)
            {
                UpdateCredentialsList();
                credentialsComboBox.Text = cred.CredentialsName;
            }
        }

        void guestListView_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            if (guestListView.CheckedItems.Count > 0)
            {
                addButton.Enabled = true;
            }
            else
            {
                addButton.Enabled = false;
            }
        }

        void guestListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (guestListView.SelectedItems.Count > 0)
            {
                guestListView.SelectedItems[0].Checked = (!guestListView.SelectedItems[0].Checked);
                guestListView.SelectedItems[0].Selected = false;
            }
        }

        void GuestImport_Load(object sender, EventArgs e)
        {
            UpdateCredentialsList();

            if (_credentials != null)
            {
                credentialsComboBox.Text = _credentials;
            }

            this.Text = String.Format("Import Guests from {0}", _hostName);
            listGuestThread = new BackgroundWorker();
            listGuestThread.DoWork += new DoWorkEventHandler(listGuestThread_DoWork);
            listGuestThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(listGuestThread_RunWorkerCompleted);
            listGuestThread.WorkerSupportsCancellation = true;
            listGuestThread.RunWorkerAsync();
        }

        void listGuestThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            SetProgressBarStyle(ref queryProgressBar, ProgressBarStyle.Blocks);

            if (guests.Count > 1)
            {
                guests.RemoveAt(0);

                foreach (string guest in guests)
                {
                    AddItemToListView(ref guestListView, AutoGuessGuestName(guest), guest);
                }
            }
            else
            {
                MessageBox.Show(String.Format("No Guests were found on {0}.\r\rPlease ensure the Host is available and correctly configured.\r\rNOTE: For VMware Workstation, Player and Fusion, only Guests that are powered on can be queried.", _hostName), "No Guests Found", MessageBoxButtons.OK, MessageBoxIcon.Information);
                this.Close();
            }
        }

        void listGuestThread_DoWork(object sender, DoWorkEventArgs e)
        {
            SetProgressBarStyle(ref queryProgressBar, ProgressBarStyle.Marquee);

            if (guests != null)
            {
                guests.Clear();
            }

            string username = null;
            string password = null;
            int exitCode;
            vmrunGUIXmlWrapper guiXmlWrapper = new vmrunGUIXmlWrapper(_guiXmlPath);
            guiXmlWrapper.GetCredentials(guiXmlWrapper.GetHostChildNodeInnerText(_hostName, "credentials"), out username, out password);
            listVMReturn = new vmrunCLIWrapper(_vmrunPath, guiXmlWrapper.GetHostChildNodeInnerText(_hostName, "type"), guiXmlWrapper.GetHostChildNodeInnerText(_hostName, "arguments"), username, password, null, null, "listRegisteredVM").ExecuteCommand(30, out guests, out exitCode);

            if (!listVMReturn)
            {
                listVMReturn = new vmrunCLIWrapper(_vmrunPath, guiXmlWrapper.GetHostChildNodeInnerText(_hostName, "type"), guiXmlWrapper.GetHostChildNodeInnerText(_hostName, "arguments"), username, password, null, null, "list").ExecuteCommand(30, out guests, out exitCode);
            }

            if (!listVMReturn)
            {
                guests.Clear();
            }
        }

        void AddItemToListView(ref ListView lv, string text, string tag)
        {
            if (InvokeRequired)
            {
                Invoke(new AddItemToListViewDelegate(AddItemToListView), new object[] { lv, text, tag });
            }
            else
            {
                ListViewItem lvi = lv.Items.Add(text);
                lvi.Tag = tag;
                lvi.Checked = true;
            }
        }

        void SetProgressBarStyle(ref ProgressBar pb, ProgressBarStyle style)
        {
            if (InvokeRequired)
            {
                Invoke(new SetProgressBarStyleDelegate(SetProgressBarStyle), new object[] { pb, style });
            }
            else
            {
                pb.Style = style;
            }
        }

        void UpdateCredentialsList()
        {
            credentialsComboBox.Items.Clear();

            foreach (string credentials in new vmrunGUIXmlWrapper(_guiXmlPath).GetCredentialsNames())
            {
                credentialsComboBox.Items.Add(credentials);
            }
        }

        string AutoGuessGuestName(string vmxPath)
        {
            string guestName = vmxPath;

            if (guestName.EndsWith(".vmx"))
            {
                guestName = guestName.Substring(guestName.LastIndexOfAny(new char[] { Convert.ToChar("\\"), Convert.ToChar("/") }) + 1).Replace(".vmx", String.Empty);
            }

            return guestName;
        }
    }
}
